DNSド素人がdigコマンドとRoute 53を使って、DNSについてあれこれ学んでみた
「やだ、、、DNS、、、怖い・・・」
自分は今までDNS全般についてずーっと苦手意識が強かったんですが、弊社大瀧が、DNSの社内勉強会を開催したのをきっかけに、今一度、digコマンドとRoute 53を利用しながらDNSの基礎について学んでみたので、その過程をご報告します。
digコマンドは、DNSの動作を確認する時のデファクトスタンダードと言えるコマンドですが、残念ながらWindowsには標準実装されていません。が、今回はEC2を利用しているので、Windowsな方も大丈夫です。
この記事を読めば、digコマンドの基本的な使い方と、DNSの挙動の基本的なところが把握できるかと思います。
目次は、こんな感じ。
- 検証用の環境を構築
- digコマンドの基本的な利用方法を学ぶ
- EC2でdigコマンドをあれこれ試してみる
- Route 53のプライベートホストゾーンを作成し、DNSレコードを編集してみる
ほな、気軽にいってみましょ。
__ (祭) ∧ ∧ Y ( ゚Д゚) Φ[_ソ__y_l〉 DNSダワッショイ |_|_| し'´J
検証用の環境を構築
以下の構成を作成します。フツーのVPCとEC2です。
作成手順の詳細は省略します。下記公式ドキュメントなどをご参照ください。
ざっくりとした手順はこちら。
- VPC(dns-test-vpc)を作成する
- VPCのDNS解決とDNSホスト名をTrueに設定する(重要)
- インターネットゲートウェイを作成し、VPC(dns-test-vpc)に割り当てる
- サブネット(subnet01)を作成する
- サブネット(subnet01)に割り当ててるルーティングテーブルに、「送信先:0.0.0.0/0」にインターネットゲートウェイを割り当てる
- EC2インスタンス、app01、app02を作成する
Route 53のプライベートホストゾーンの作成が必要ですが、そこは後ほど説明します。
これから記載する全てのコマンドは、VPC内のEC2から実行していますのでご注意ください。
digコマンドの基本的な利用方法を学ぶ
これからdigコマンドを利用して、DNSの挙動を確認していくわけですが、最初にdigコマンドの利用方法を確認します。
digコマンドの基本使用例
$dig @DNSサーバー example.com クエリタイプ
オプション名 | 必須(?) | 解説 |
---|---|---|
@DNSサーバー | 任意 | 名前解決に利用するDNSサーバーを指定 |
example.com | 必須 | 対象ドメイン名 |
クエリタイプ | 任意 | 問い合わせるDNSのリソースレコードタイプを指定 |
クエリタイプに指定できるタイプの一覧(一部)
リソースレコードタイプ | 役割 |
---|---|
A | ホストのアドレス |
CNAME | ホストの別名 |
MX | ドメインのメール交換ホスト |
NS | ドメインのネームサーバ |
TXT | テキスト |
ANY | 全てのタイプの全てのレコードを返す |
試しに、digコマンドを利用して、yahoo.co.jpに名前解決してみましょう。
$ dig yahoo.co.jp ; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.62.rc1.56.amzn1 <<>> yahoo.co.jp ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 57517 ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;yahoo.co.jp. IN A ;; ANSWER SECTION: yahoo.co.jp. 60 IN A 182.22.59.229 yahoo.co.jp. 60 IN A 183.79.135.206 ;; Query time: 5 msec ;; SERVER: 10.0.0.2#53(10.0.0.2) ;; WHEN: Fri Feb 2 23:53:47 2018 ;; MSG SIZE rcvd: 61
なんや、わらわら出力されましたが、以降で各セクションの内容を解説していきます。
digコマンド結果の確認方法
HEADERセクション
; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.62.rc1.56.amzn1 <<>> yahoo.co.jp ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 57517 ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0
ここでは、statusに注目します。
- NOERROR:正常にクエリが実行されている
- NXDOMAIN:ドメインが存在しない
- REFUSED:何らかの理由でクエリが拒否されている
NOERROR以外のstatusが返っている場合は、そのクエリは失敗しているので、注意しましょう。
QUESTIONセクション
;; QUESTION SECTION: ;yahoo.co.jp. IN A
DNSへの問い合わせ内容が表示されています。ここでは、yahoo.co.jpドメインのAレコードを問い合わせしています。INはインターネットの略で、クエリ全般これがついているので、とりあえず「そんなもんだ」と覚えておきましょう。
ANSWERセクション
;; ANSWER SECTION: yahoo.co.jp. 60 IN A 182.22.59.229 yahoo.co.jp. 60 IN A 183.79.135.206
問い合わせ内容に対する返答です。ここでは、yahoo.co.jpのエイリアス(Aレコード)に、2つのIPアドレスがあることがわかります。また、ここの60はTTL(キャッシュの生存期間)を表します。
試しに、このIPアドレスにWebブラウザでアクセスしてみてください。yahooのトップページが表示されます。
締めのセクション
;; Query time: 5 msec ;; SERVER: 10.0.0.2#53(10.0.0.2) ;; WHEN: Fri Feb 2 23:53:47 2018 ;; MSG SIZE rcvd: 61
最後に、クエリにかかった時間や時刻が表示されます。ここで一番大事なのが、SERVER。ここに利用したDNSサーバーが表示されます。
digコマンドにおいて、DNSサーバーの指定は必須ではありません。そして、digコマンドを実行した環境により利用されるDNSサーバーは異なるので、「あっちとこっちで、結果が違うやん」という場合、大抵はこのクエリに利用したDNSサーバーが異なっていたというパターンが多いです。
ちなみに、サーバー名の後ろ「#53」は、DNSクエリに利用したポート番号53を表しています。Route 53の名前の由来ですね。
digコマンドの別のオプション
digコマンドには、他にも便利なオプションが存在するので、それらを紹介します。
結果をシンプルに表示したい
+shortオプションを利用すると、クエリ結果がシンプルに表示されます。
$ dig yahoo.co.jp +short 182.22.59.229 183.79.135.206
シェルスクリプトの中で使ったりするには、便利ですね。
ルートからDNSをたどる
+traceオプションを利用すると、強制的にルートサーバーから順番にたどることができます。
$ dig yahoo.co.jp +trace
再帰問い合わせをしない
+norecオプションを利用すると、再帰問い合わせをオフにして、名前解決を実行します。
$ dig yahoo.co.jp +norec
EC2でdigコマンドをあれこれ試してみる
ここから、EC2でdigコマンドをあれこれ試してみます。もう一度、yahoo.co.jpに対して、クエリを流します。
$ dig yahoo.co.jp ; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.62.rc1.56.amzn1 <<>> yahoo.co.jp ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 57517 ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;yahoo.co.jp. IN A ;; ANSWER SECTION: yahoo.co.jp. 60 IN A 182.22.59.229 yahoo.co.jp. 60 IN A 183.79.135.206 ;; Query time: 5 msec ;; SERVER: 10.0.0.2#53(10.0.0.2) ;; WHEN: Fri Feb 2 23:53:47 2018 ;; MSG SIZE rcvd: 61
VPC内で利用するネームサーバ(DNS)のIPアドレスは?
ここでポイントなのが、DNSクエリを発行した時に利用されるDNSサーバ。digの結果を確認すると、下の方、;; SERVER: 10.0.0.2#53(10.0.0.2)で、DNSサーバとして、10.0.0.2のプライベートIPアドレスを利用しています。
これは、VPC内のサブネット内であらかじめAWS側でDNSサーバとして予約されているIPアドレスで、サブネット内IPアドレスの2つ目が、Amazonが提供するDNSサーバとして利用されます。
今回は、サブネットのCIDRが10.0.0.0/24なので、DNSサーバに10.0.0.2が割り当てられているということになります。
詳細は、公式ドキュメントの「VPC での DNS の使用 - Amazon Virtual Private Cloud」を参照ください。
ちなみにこのアドレスは、下記ファイルに記載されています。
$ cat /etc/resolv.conf ; generated by /sbin/dhclient-script search ap-northeast-1.compute.internal options timeout:2 attempts:5 nameserver 10.0.0.2
このファイルを編集すればデフォルトで利用するDNSサーバを変更できますが、恐らくはアンチパターンなので安易な変更はやめておきましょう。
Amazon提供のDNSサーバーをVPC内から利用すると、TTLが最大60秒?
上で説明したAmazon提供のDNSですが、あれこれ試してみた結果、VPC内から発行する全てのクエリのTTLが上限が60秒に設定されるようです。
yahoo.co.jpへのクエリで、DNSサーバーにAmazon提供DNSと、Googleが提供するグローバルDNS(8.8.8.8)を利用した時の差分がこちら。
$ dig @10.0.0.2 yahoo.co.jp > dns_amazon.txt $ dig @8.8.8.8 yahoo.co.jp > dns_google.txt $ diff dns_amazon.txt dns_google.txt 2c2 < ; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.62.rc1.56.amzn1 <<>> @10.0.0.2 yahoo.co.jp --- > ; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.62.rc1.56.amzn1 <<>> @8.8.8.8 yahoo.co.jp 6c6 < ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28002 --- > ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 94 13,14c13,14 < yahoo.co.jp. 60 IN A 182.22.59.229 < yahoo.co.jp. 60 IN A 183.79.135.206 --- > yahoo.co.jp. 211 IN A 182.22.59.229 > yahoo.co.jp. 211 IN A 183.79.135.206 16,18c16,18 < ;; Query time: 5 msec < ;; SERVER: 10.0.0.2#53(10.0.0.2) < ;; WHEN: Sat Feb 3 22:41:45 2018 --- > ;; Query time: 37 msec > ;; SERVER: 8.8.8.8#53(8.8.8.8) > ;; WHEN: Sat Feb 3 22:41:56 2018
ANSWERセクションのAレコード部分のTTLをみると、VPC内のAmazonDNSを利用した場合60、GoogleグローバルDNSを利用した時に211になっています。
逆に、TTLが5秒など60秒より短めに設定されているレコードの場合は、5秒で返却されます。
この挙動について公式ドキュメントが見当たらなかったのですが、VPC内からDNSを利用する場合は、TTLを長く設定する必要性がないので、最大60秒と短めに設定されていると推察されます。ただ、この仕様は将来的に変更される可能性もありますので、あくまで現時点での挙動として認識していただければと思います。
同一VPC内への名前解決を試してみた
試しに、パブリックリソースではなく、同一VPC内に作った別のEC2インスタンスのDNSホスト名に対して名前解決してみます。
$ dig ec2-176-32-88-158.ap-northeast-1.compute.amazonaws.com ; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.62.rc1.56.amzn1 <<>> ec2-176-32-88-158.ap-northeast-1.compute.amazonaws.com ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 33890 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;ec2-176-32-88-158.ap-northeast-1.compute.amazonaws.com. IN A ;; ANSWER SECTION: ec2-176-32-88-158.ap-northeast-1.compute.amazonaws.com. 20 IN A 10.0.0.145 ;; Query time: 1 msec ;; SERVER: 10.0.0.2#53(10.0.0.2) ;; WHEN: Sat Feb 3 00:08:10 2018 ;; MSG SIZE rcvd: 88
同じように、10.0.0.2に問い合わせて、プライベートIPアドレスの10.0.0.145がかえってきました。まぁ当然の仕様ですね。
Route 53のプライベートホストゾーンを作成し、DNSレコードを編集してみる
AWSのRoute 53には、プライベートホストゾーンという、VPC内専用のDNSレコードを作成する機能があります。DNSサーバーの構築は素人にはなかなか敷居が高いですが、Route 53を利用して、お手軽にDNSレコードを編集してみましょう。
参考:プライベートホストゾーンの使用 - Amazon Route 53
AWSコンソールから[Route 53]を開き、[Create Hosted Zone]から設定します。VPC IDには、このプライベートホストゾーンを割り当てるVPCを設定します。
そうすると、NSレコードとSOAレコードがセットされたプライベートホストゾーンが自動的に作成されます。
試しに、VPC内のEC2からdigで確認してみると、先程作成したレコードが登録されているのがわかります。
$ dig ANY example.com ; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.62.rc1.56.amzn1 <<>> ANY example.com ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2254 ;; flags: qr rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;example.com. IN ANY ;; ANSWER SECTION: example.com. 60 IN SOA ns-1536.awsdns-00.co.uk. awsdns-hostmaster.amazon.com. 1 7200 900 1209600 86400 example.com. 60 IN NS ns-1536.awsdns-00.co.uk. example.com. 60 IN NS ns-0.awsdns-00.com. example.com. 60 IN NS ns-512.awsdns-00.net. example.com. 60 IN NS ns-1024.awsdns-00.org. ;; Query time: 2 msec ;; SERVER: 10.0.0.2#53(10.0.0.2) ;; WHEN: Sat Feb 3 02:32:50 2018 ;; MSG SIZE rcvd: 225
Aレコードを設定し、独自ドメインでEC2に名前解決する
このゾーンに対して、EC2インスタンスプライベートIPアドレスへのAレコードを設定します。
結果を確認します。
$ dig app02.example.com ; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.62.rc1.56.amzn1 <<>> app02.example.com ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62131 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;app02.example.com. IN A ;; ANSWER SECTION: app02.example.com. 16 IN A 10.0.0.145 ;; Query time: 0 msec ;; SERVER: 10.0.0.2#53(10.0.0.2) ;; WHEN: Sat Feb 3 02:41:13 2018 ;; MSG SIZE rcvd: 51
無事、app02.example.comを利用して、プライベートIPアドレスへの名前解決ができるようになりました。
VPC内でEC2インスタンスやRDSに接続する時、IPアドレスやRDSのエンドポイントを直接指定せずに、プライベートホストゾーンで別名を指定してそれを利用する方法も有ります。そうすると、インスタンスやRDSの再作成時に、変更箇所をRoute 53の設定だけで済ますことができ、EC2内の設定を変更する必要がありません。
運用保守時には非常に便利な機能なので、適宜ご活用いただければと思います。
適当なTXTレコードを設定してみる
他のレコードも設定できます。TXTレコードの場合は、TypeにTXTを指定しましょう。
$ dig txt hamako9999.example.com ; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.62.rc1.56.amzn1 <<>> txt hamako9999.example.com ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 25113 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;hamako9999.example.com. IN TXT ;; ANSWER SECTION: hamako9999.example.com. 60 IN TXT "dosukoi wassyoi" ;; Query time: 1 msec ;; SERVER: 10.0.0.2#53(10.0.0.2) ;; WHEN: Sat Feb 3 03:51:32 2018 ;; MSG SIZE rcvd: 68
無事、「dosukoi wassyoi」が返却されましたね。よござんす!!
digコマンドとRoute 53を使って、DNSについて理解を深めよう!
AWSのVPCにEC2を作成し、Amazon提供のDNSサーバーの挙動と、Route 53によるプライベートホストゾーンのレコード編集結果を、digコマンドでいろいろ試してみました。
digコマンドは機能が豊富で非常に便利なのですが、できることが多いがゆえに、その結果の見方が複雑であったり、動作がわかりにくい点もあるんじゃないでしょうか。正直自分も、最初は「ええ?これどないなってんねん?」となってしまいました。
今回の記事をきっかけに、digコマンドとDNSについて理解が深まれば幸いです。
それでは、今日はこのへんで。濱田(@hamako9999)でした。
おすすめ書籍
自分がDNSを勉強するにあたり、読んでいる本です。対話形式なので記述が冗長に感じるかもですが、丁寧に順を追って解説してくれるので、非常に分かりやすい。「DNS学ぶんだったら、最初はコレでええやろ」と自信をもってオススメします。